from constants import *
import pygame,random,time
from task import Task

#####################################################
#                                                   #
#  DS Class:                                        # 
#                                                   #
#  The DS class serves as a generic data structure  #
#  class that provides basic information and        #
#  functions that are relevant to most              #
#  data structures.                                 #
#                                                   # 
#  Author: Felix Rohrer                             #     
#  Course: CS MET 575                               #
#  Year:   2011                                     #
#                                                   #
#####################################################

class DS(object):

  def __init__(self,numOfElem, pos, name, drawAreaDim):
    super(DS, self).__init__()

    # initialize pygame
    pygame.init()

    # set data structres name
    self.name = name

    # create queue
    self.pos = pos
    self.posOffset = [None, None]
    self.size = [50,50]
    self.drawArea = drawAreaDim

    # create queue objects
    self.numOfElem = numOfElem
    self.tasks = [None] * numOfElem
    self.rects = []
    self.tail = 0
    self.head = self.tasks[0]
    self.iterPtr = 0

    # define font
    self.textFont = pygame.font.SysFont(SYS_FONT,SYS_FONT_SIZE)

    for i in range(self.numOfElem):
      # add visual represenation of this list item
      self.rects.append(pygame.Rect(self.pos[0]+self.size[0]*i, self.pos[1], self.size[0], self.size[1]))

  def display(self, canvas,bgColor=(255,255,255)):
    # draw rects that belong currently to the queue
    for r in self.rects:
      pygame.draw.rect(canvas, bgColor,r, 0)
      pygame.draw.rect(canvas, (0,0,0),r, 1)

  # increase tail poiner
  def incTail(self):
    if self.tail < self.numOfElem -1:
      self.tail +=1

  # decrease tail poiner
  def decTail(self):
    if self.tail > 0 and self.tasks[self.tail-1] is None:
      self.tail -=1

  # defines, if this data structure is execution unit (like CPU)
  def isExecutionUnit(self):
    return False

  # return this DS length
  def getLength(self):
    return self.numOfElem

  # check if queue is empty
  def isEmpty(self):
    if self.tasks[0] is None:
      return True
    return False

  # remove all tasks from this queue immediately
  def makeEmpty(self):
    self.tail = 0
    self.head = self.tasks[0]
    for x in range(len(self.tasks)):
      self.tasks[x] = None

  # check collision between mouse and this data structure
  def collision(self, pointer):
    if pointer[0] > self.pos[0] and pointer[0] < self.pos[0]+self.size[0]*self.numOfElem \
                           and pointer[1] > self.pos[1] and pointer[1] < self.pos[1]+self.size[1]:
      return True
    return False

  def dropped(self):
    self.posOffset[0] = None
    self.posOffset[1] = None

  def setPos(self, pos):
      # save the offset of where the user clicked on the task
      # relative to the tasks left upper corner (self.pos) 

      if self.posOffset[0] is None:
        self.posOffset[0] = pos[0] - self.pos[0]
        self.posOffset[1] = pos[1] - self.pos[1]

      # set new x coordinate of this task
      if pos[0] < self.posOffset[0]:
	self.pos[0] = 1
      elif pos[0] > (self.drawArea[0] - self.size[0]*self.numOfElem + self.posOffset[0]):
	self.pos[0] = self.drawArea[0] - self.size[0]*self.numOfElem - 1
      else:
        self.pos[0] = pos[0] - self.posOffset[0]

      # find new y coordinate of this task
      if pos[1] < self.posOffset[1]:
	self.pos[1] = 1
      elif pos[1] > (self.drawArea[1] - self.size[1]*2/3):
	self.pos[1] = self.drawArea[1] - self.size[1]*3/2
      else:
        self.pos[1] = pos[1] - self.posOffset[1]
      
      for r in range(len(self.rects)):
        self.rects[r].left = self.pos[0]+self.size[0]*r
        self.rects[r].top = self.pos[1]

      for t in range(len(self.tasks)):
        if self.tasks[t] is not None:
          self.tasks[t].setPos((self.pos[0]+10+50*t,self.pos[1]+10),ignoreNoMove=True)

  # return task that will be removed next
  def peakNext(self):
    return self.tasks[0]

  # get this data structures' head position
  def getHeadPos(self):
    return (self.pos[0]+10, self.pos[1]+self.size[1]/4)

  # get this data structures' tail position
  def getTailPos(self):
    return (self.pos[0]+50*self.numOfElem-40, self.pos[1]+self.size[1]/4)

  # get the tasks position
  def getTaskPos(self,task):
    for pos in range(len(self.tasks)):
      if self.tasks[pos] == task:
        return (self.pos[0]+50*(pos+1)-40, self.pos[1])
    return False

  # empty all data structures
  def empty(self):
    self.textFont = None
    del self.tasks[:]
    del self.rects[:]
